/*
 * HMACFrame.java
 *
 * Created on 10. Oktober 2008, 13:36
 */
package jcrypter.hmac;

import java.io.*;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.ResourceBundle;
import java.util.logging.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import jcrypter.JCrypterFrame;
import org.bouncycastle.util.encoders.Base64;

/**
 *
 * @author  uli
 */
public class HMACFrame extends javax.swing.JFrame
{

    /** Creates new form HMACFrame */
    public HMACFrame()
    {
        initComponents();
        //Add the digest algorithms to the combo box
        for (String digest : JCrypterFrame.mainFrame.getMacs())
        {
            digestComboBox.addItem(digest);
        }
        //Set SHA-256 as default
        digestComboBox.setSelectedItem("SHA256"); //NOI18N
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        inputLabel = new javax.swing.JLabel();
        inputScrollPane = new javax.swing.JScrollPane();
        inputField = new javax.swing.JTextArea();
        passwordField = new javax.swing.JPasswordField();
        passwordLabel = new javax.swing.JLabel();
        okButton = new javax.swing.JButton();
        verifyCheckbox = new javax.swing.JCheckBox();
        hmacLabel = new javax.swing.JLabel();
        hmacField = new javax.swing.JTextField();
        digestComboBox = new javax.swing.JComboBox();
        digestLabel = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        loadFromFileMenuItem = new javax.swing.JMenuItem();
        saveToFileMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle(i18n.getString("HMACFrame.title")); // NOI18N

        inputLabel.setText(i18n.getString("HMACFrame.inputLabel.text")); // NOI18N

        inputField.setColumns(20);
        inputField.setRows(5);
        inputScrollPane.setViewportView(inputField);

        passwordLabel.setDisplayedMnemonic('p');
        passwordLabel.setText(i18n.getString("HMACFrame.passwordLabel.text")); // NOI18N

        okButton.setMnemonic('o');
        okButton.setText(i18n.getString("HMACFrame.okButton.text")); // NOI18N
        okButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                okButtonMouseClicked(evt);
            }
        });

        verifyCheckbox.setText(i18n.getString("HMACFrame.verifyCheckbox.text")); // NOI18N

        hmacLabel.setText(i18n.getString("HMACFrame.hmacLabel.text")); // NOI18N

        hmacField.setText(i18n.getString("HMACFrame.hmacField.text")); // NOI18N

        digestLabel.setText(i18n.getString("HMACFrame.digestLabel.text")); // NOI18N

        fileMenu.setMnemonic('f');
        fileMenu.setText(i18n.getString("HMACFrame.fileMenu.text")); // NOI18N

        loadFromFileMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        loadFromFileMenuItem.setMnemonic('l');
        loadFromFileMenuItem.setText(i18n.getString("HMACFrame.loadFromFileMenuItem.text")); // NOI18N
        loadFromFileMenuItem.setToolTipText(i18n.getString("HMACFrame.loadFromFileMenuItem.toolTipText")); // NOI18N
        loadFromFileMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                loadFromFileMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(loadFromFileMenuItem);

        saveToFileMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        saveToFileMenuItem.setMnemonic('s');
        saveToFileMenuItem.setText(i18n.getString("HMACFrame.saveToFileMenuItem.text")); // NOI18N
        saveToFileMenuItem.setToolTipText(i18n.getString("HMACFrame.saveToFileMenuItem.toolTipText")); // NOI18N
        saveToFileMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveToFileMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(saveToFileMenuItem);

        menuBar.add(fileMenu);

        setJMenuBar(menuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(inputLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(inputScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE))
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                .addComponent(passwordLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(passwordField, javax.swing.GroupLayout.DEFAULT_SIZE, 227, Short.MAX_VALUE))))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(50, 50, 50)
                        .addComponent(verifyCheckbox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(okButton, javax.swing.GroupLayout.DEFAULT_SIZE, 201, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(hmacLabel)
                            .addComponent(digestLabel))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(digestComboBox, 0, 246, Short.MAX_VALUE)
                            .addComponent(hmacField, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(inputScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 180, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(inputLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(passwordLabel)
                    .addComponent(passwordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(verifyCheckbox)
                    .addComponent(okButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(digestLabel)
                    .addComponent(digestComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(hmacField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(hmacLabel))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void loadFromFileMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_loadFromFileMenuItemActionPerformed
    FileInputStream fin = null;
    try
    {
        fileChooser.showOpenDialog(this);
        File file = fileChooser.getSelectedFile();
        byte[] buffer = new byte[(int) file.length()];
        fin = new FileInputStream(file);
        fin.read(buffer);
        fin.close();
        inputField.setText(new String(buffer));
    }
    catch (IOException ex)
    {
            JOptionPane.showMessageDialog(this, ex.getLocalizedMessage(), i18n.getString("IO_Error"), JOptionPane.ERROR_MESSAGE);
    }
    finally
    {
        try
        {
            fin.close();
        }
        catch (IOException ex)
        {
            Logger.getLogger(JCrypterFrame.class.getName()).log(Level.SEVERE, null, ex);
            ex.printStackTrace();
        }
    }
}//GEN-LAST:event_loadFromFileMenuItemActionPerformed

private void saveToFileMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveToFileMenuItemActionPerformed
    FileOutputStream fout = null;
    try
    {
        fileChooser.showSaveDialog(this);
        File file = fileChooser.getSelectedFile();
        byte[] buffer = hmacField.getText().getBytes();
        fout = new FileOutputStream(file);
        fout.write(buffer);
        fout.close();
    }
    catch (IOException ex)
    {
            JOptionPane.showMessageDialog(this, ex.getLocalizedMessage(), i18n.getString("IO_Error"), JOptionPane.ERROR_MESSAGE);
    }
    finally
    {
        try
        {
            fout.close();
        }
        catch (IOException ex)
        {
            Logger.getLogger(JCrypterFrame.class.getName()).log(Level.SEVERE, null, ex);
            ex.printStackTrace();
        }
    }
}//GEN-LAST:event_saveToFileMenuItemActionPerformed

private void okButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_okButtonMouseClicked
    if (verifyCheckbox.isSelected())
    {
        if(verifyHMAC(inputField.getText(), passwordField.getPassword(),(String) digestComboBox.getSelectedItem(), hmacField.getText()))
        {
            JOptionPane.showMessageDialog(this, i18n.getString("The_HMAC_has_been_validated_successfully"), i18n.getString("Validation_success"), JOptionPane.INFORMATION_MESSAGE);
        }
        else
        {
            JOptionPane.showMessageDialog(this,
                i18n.getString("This_HMAC_is_not_valid!"),
                i18n.getString("Verification_error"),
                JOptionPane.ERROR_MESSAGE);
        }
    }
    else
    {
        hmacField.setText(generateHMAC(inputField.getText(), passwordField.getPassword(),(String) digestComboBox.getSelectedItem()));
    }
}//GEN-LAST:event_okButtonMouseClicked

    /**
     * @param args the command line arguments
     */
    public static void main(String args[])
    {
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new HMACFrame().setVisible(true);
            }
        });
    }
    JFileChooser fileChooser = JCrypterFrame.mainFrame.fileChooser;
    ResourceBundle i18n = ResourceBundle.getBundle("jcrypter/hmac/Bundle");
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JComboBox digestComboBox;
    private javax.swing.JLabel digestLabel;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JTextField hmacField;
    private javax.swing.JLabel hmacLabel;
    private javax.swing.JTextArea inputField;
    private javax.swing.JLabel inputLabel;
    private javax.swing.JScrollPane inputScrollPane;
    private javax.swing.JMenuItem loadFromFileMenuItem;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JButton okButton;
    private javax.swing.JPasswordField passwordField;
    private javax.swing.JLabel passwordLabel;
    private javax.swing.JMenuItem saveToFileMenuItem;
    private javax.swing.JCheckBox verifyCheckbox;
    // End of variables declaration//GEN-END:variables
    
    public static String generateHMAC(String input, char[] password, String algorithm)
    {
        try
        {
            //Get the data needed by the HMAC algorithm
            String hmacAlgorithm = "Hmac" + algorithm; //NOI18N
            byte[] rawPassword = new String(password).getBytes();
            Key hmacKey = new SecretKeySpec(rawPassword, hmacAlgorithm);
            byte[] inputBytes = input.getBytes();

            //Calculate the HMAC
            Mac hmac = Mac.getInstance(hmacAlgorithm);
            hmac.init(hmacKey);
            byte[] hmacBytes = hmac.doFinal(inputBytes);

            //Print the B64-encoded HMAC to the HMAC output field
            return new String(Base64.encode(hmacBytes));
        }
        catch (InvalidKeyException ex)
        {
            Logger.getLogger(HMACFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (NoSuchAlgorithmException ex)
        {
            Logger.getLogger(HMACFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
    
    public static boolean verifyHMAC(String input, char[] password, String algorithm, String hmac)
    {
        return generateHMAC(input, password, algorithm).equals(hmac);
    }
}
